#include "attendancetimemanager.h"
#include "attendanceviewmodelmanager.h"
#include "qvariant.h"
#include "setattetimewidget.h"
#include "syssetwidget.h"

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDate>

AttendanceViewModelManager::AttendanceViewModelManager() {

}

ClockResult AttendanceViewModelManager::clockInOut(QSqlDatabase &db, const QString &rfidCard) {
    // QSqlDatabase db = QSqlDatabase::database();
    ClockResult result;
    result.clockTime = QDateTime::currentDateTime();

    if (!db.isOpen()) {
        result.success = false;
        result.message = "数据库未连接";
        return result;
    }

    db.transaction();  // 开启事务

    try {
        // 步骤1：验证员工是否存在
        QSqlQuery empQuery(db);
        empQuery.prepare("SELECT emp_id FROM employee WHERE card_id = ?");
        empQuery.addBindValue(QVariant(rfidCard));

        if (!empQuery.exec() || !empQuery.next()) {
            result.success = false;
            result.message = "无效的卡号或员工不存在";
            db.rollback();
            return result;
        }

        const int empId = empQuery.value(0).toInt();

        // 步骤2：检查当日考勤记录
        QSqlQuery attQuery(db);
        attQuery.prepare(
            "SELECT att_id, clock_in, clock_out "
            "FROM attendance "
            "WHERE emp_id = ? AND check_date = DATE('now')"
            );
        attQuery.addBindValue(empId);

        if (!attQuery.exec()) {
            throw std::runtime_error("考勤查询失败");
        }
        // 获取当前日期是周几
        const int weekday = result.clockTime.date().dayOfWeek();
        QString weekdayStr = AttendanceTimeManager::m_weekdayMap.value(weekday);    // 获取索引对应的星期几
        DailySettings settings = AttendanceTimeManager::m_settings.value(weekdayStr);    // 获取星期几对应的打卡设置

        // 步骤3：判断打卡类型
        if (attQuery.next()) {
            // 存在记录
            const bool hasClockIn = !attQuery.value("clock_in").isNull();
            const bool hasClockOut = !attQuery.value("clock_out").isNull();
                        
            // 下班打卡
            QSqlQuery updateQuery(db);
            updateQuery.prepare(
                "UPDATE attendance SET "
                "clock_out = ?, "
                "status = CASE "
                "   WHEN TIME(?) < ? THEN '早退' "
                "   ELSE status "
                "END "
                "WHERE att_id = ?"
                );
            updateQuery.addBindValue(result.clockTime.toString("yyyy-MM-dd hh:mm:ss"));    // 打卡时间日期
            updateQuery.addBindValue(result.clockTime.toString("hh:mm:ss"));    // 打卡时间
            updateQuery.addBindValue(settings.endTime.toString("hh:mm:ss"));    // 规定的下班时间
            updateQuery.addBindValue(attQuery.value("att_id"));

            if (!updateQuery.exec()) {
                throw std::runtime_error("下班打卡失败");
            }

            result.success = true;
            result.clockType = "下班";
            result.message = "下班打卡成功";
        
            
            if (hasClockIn) {
                // 重复打卡
                result.clockType = "重复打卡";
                result.message = "已完成当日考勤记录";
            }
        } else {
            // 上班打卡（插入新记录）
            QSqlQuery insertQuery(db);
            insertQuery.prepare(
                "INSERT INTO attendance "
                "(emp_id, check_date, clock_in, status) "
                "VALUES (?, DATE('now'), ?, "
                "   CASE "
                "       WHEN TIME(?) > ? THEN '迟到' "
                "       ELSE '正常' "
                "   END)"
                );
            insertQuery.addBindValue(empId);
            insertQuery.addBindValue(result.clockTime.toString("yyyy-MM-dd hh:mm:ss"));  // 打卡时间日期
            insertQuery.addBindValue(result.clockTime.toString("hh:mm:ss"));    // 打卡时间
            insertQuery.addBindValue(settings.startTime.toString("hh:mm:ss"));  // 规定的上班时间

            if (!insertQuery.exec()) {
                throw std::runtime_error("上班打卡失败");
            }

            result.success = true;
            result.clockType = "上班";
            result.message = "上班打卡成功";
        }

        db.commit();
        return result;
    } catch (const std::exception &e) {
        db.rollback();
        result.success = false;
        result.message = QString("操作失败: %1").arg(e.what());
        return result;
    }
}
